﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Reflection;

using INI;

using FullMotion.LiveForSpeed.InSim;
using FullMotion.LiveForSpeed.InSim.Enums;
using FullMotion.LiveForSpeed.InSim.Events;

namespace F1_Start_Sequence
{
    class Program
    {

        private string ip;
        private int port;
        private string adminPass;
        private Boolean useTCP = true;
        private char prefix;
        private string raceState;
        private string Track;
        private Boolean boolStartActivate = false;
        private Boolean boolRecordActivate = false;
        private Boolean FullGridRecord = false;
        private byte PassConnID = 0;
        private int StartForm = 1; // 1=Standing start 2=SC Start
        private int position = 0;
        private Boolean Ready = false;
        private int racelaps = 0;
        private Boolean isHours;

        private string ProgramTitle;
        private string ProgramVersion;
        private string ProgramCompany;

        private InSimHandler handler = new InSimHandler();
        private Hashtable racerdatabase = new Hashtable();
        private Hashtable reodatabase = new Hashtable();
        private TrackRaceLocation t = new TrackRaceLocation();

        private int onemeter = 65536;
        private int centimeter = 655;
        private int sensitivity = 30;

        private LfsButton[] lights = new LfsButton[5];
        private LfsButton RacerStartLocation = new LfsButton(5);
        private LfsButton StartHeader = new LfsButton(6);
        private LfsButton RecordHeader = new LfsButton(7);
        private LfsButton RecordTrack = new LfsButton(8);
        private LfsButton RecordPosition = new LfsButton(9);
        private LfsButton RecordNumber = new LfsButton(10);
        private LfsButton RecordButton = new LfsButton(11);
        private LfsButton RecordExport = new LfsButton(12);
        private LfsButton RecordClose = new LfsButton(13);
        private LfsButton StartActivate = new LfsButton(14);
        private LfsButton StartSCStand = new LfsButton(15);
        private LfsButton StartReady = new LfsButton(16);
        private LfsButton StartButton = new LfsButton(17);
        private LfsButton StartClose = new LfsButton(18);
        private LfsButton RecordPositionText = new LfsButton(19);
        private LfsButton StartRefresh = new LfsButton(20);
        private LfsButton RecordActivate = new LfsButton(21);
        private LfsButton RecordTrackText = new LfsButton(22);
        private LfsButton RecordNumberText = new LfsButton(23);
        private LfsButton StartSCStandText = new LfsButton(24);
        private LfsButton StartRacerList = new LfsButton(25);
        private LfsButton StartRaceLaps = new LfsButton(26);
        private LfsButton StartRaceLapsText = new LfsButton(27);
        private LfsButton btnFullGridRecord = new LfsButton(28);

        static void Main(string[] args)
        {
            Program p = new Program();
            p.Config();
            p.Setup();
            p.Start();
            p.Threading();
        }

        public void Config()
        {
            try
            {
                IniFile ini = new IniFile(".\\config.ini");
                ip = ini.IniReadValue("server", "ip");
                port = Convert.ToInt32(ini.IniReadValue("server", "port"));
                adminPass = ini.IniReadValue("server", "admin pass");
                prefix = Convert.ToChar(ini.IniReadValue("server", "insim prefix"));
            }
            catch (Exception)
            {

            }
        }

        public void Setup()
        {
            for (int i = 0; i < 5; i++)
            {
                lights[i] = new LfsButton((byte)i);
                lights[i].Color = ButtonColor.Dark;
                lights[i].Height = 10;
                lights[i].Width = 10;
                lights[i].Top = 20;
                lights[i].Left = (byte)((i * lights[i].Width) + 30);
                lights[i].TextAlignment = ButtonTextAlignment.Center;
                lights[i].TextColor = ButtonTextColor.Cancel;
                lights[i].Text = "O";
            }

            StartHeader.Color = ButtonColor.Dark;
            StartHeader.Height = 10;
            StartHeader.Left = 70;
            StartHeader.Text = "F1 Start Sequence - Start Race";
            StartHeader.TextAlignment = ButtonTextAlignment.Center;
            StartHeader.TextColor = ButtonTextColor.SelectedText;
            StartHeader.Top = 50;
            StartHeader.Width = 60;

            RecordHeader.Color = ButtonColor.Dark;
            RecordHeader.Height = 10;
            RecordHeader.Left = 60;
            RecordHeader.Text = "F1 Start Sequence - Record Positions";
            RecordHeader.TextAlignment = ButtonTextAlignment.Center;
            RecordHeader.TextColor = ButtonTextColor.SelectedText;
            RecordHeader.Top = 50;
            RecordHeader.Width = 80;

            RecordButton.Color = ButtonColor.Dark;
            RecordButton.Height = 10;
            RecordButton.Left = 70;
            RecordButton.Text = "Record Individual";
            RecordButton.TextAlignment = ButtonTextAlignment.Center;
            RecordButton.Top = 90;
            RecordButton.Width = 20;
            if (boolRecordActivate)
            {
                RecordButton.TextColor = ButtonTextColor.SelectedText;
                RecordButton.Clickable = true;
            }
            else
            {
                RecordButton.TextColor = ButtonTextColor.LightGrey;
                RecordButton.Clickable = false;
            }

            btnFullGridRecord.Color = ButtonColor.Dark;
            btnFullGridRecord.Height = 10;
            btnFullGridRecord.Left = 90;
            btnFullGridRecord.Text = "Record Full Grid";
            btnFullGridRecord.TextAlignment = ButtonTextAlignment.Center;
            btnFullGridRecord.Top = 90;
            btnFullGridRecord.Width = 20;
            if (boolRecordActivate)
            {
                btnFullGridRecord.TextColor = ButtonTextColor.Ok;
                btnFullGridRecord.Clickable = true;
            }
            else
            {
                btnFullGridRecord.TextColor = ButtonTextColor.Cancel;
                btnFullGridRecord.Clickable = false;
            }

            RecordActivate.Color = ButtonColor.Dark;
            RecordActivate.Height = 10;
            RecordActivate.Left = 50;
            RecordActivate.Text = "Activate";
            RecordActivate.TextAlignment = ButtonTextAlignment.Center;
            RecordActivate.Top = 90;
            RecordActivate.Width = 20;
            RecordActivate.TextColor = ButtonTextColor.Cancel;
            RecordActivate.Clickable = true;

            RecordClose.Color = ButtonColor.Dark;
            RecordClose.Height = 10;
            RecordClose.Left = 130;
            RecordClose.Text = "Close";
            RecordClose.TextAlignment = ButtonTextAlignment.Center;
            RecordClose.TextColor = ButtonTextColor.SelectedText;
            RecordClose.Top = 90;
            RecordClose.Width = 20;
            RecordClose.Clickable = true;

            RecordExport.Color = ButtonColor.Dark;
            RecordExport.Height = 10;
            RecordExport.Left = 110;
            RecordExport.Text = "Export";
            RecordExport.TextAlignment = ButtonTextAlignment.Center;
            RecordExport.Top = 90;
            RecordExport.Width = 20;
            if (boolRecordActivate)
            {
                RecordExport.Clickable = true;
                RecordExport.TextColor = ButtonTextColor.SelectedText;
            }
            else
            {
                RecordExport.Clickable = false;
                RecordExport.TextColor = ButtonTextColor.LightGrey;
            }

            RecordNumberText.Color = ButtonColor.Dark;
            RecordNumberText.Height = 10;
            RecordNumberText.Left = 80;
            RecordNumberText.Text = "Num Recorded";
            RecordNumberText.TextAlignment = ButtonTextAlignment.Center;
            RecordNumberText.TextColor = ButtonTextColor.SelectedText;
            RecordNumberText.Top = 80;
            RecordNumberText.Width = 20;

            RecordNumber.Color = ButtonColor.Dark;
            RecordNumber.Height = 10;
            RecordNumber.Left = 100;
            RecordNumber.Text = "";
            RecordNumber.TextAlignment = ButtonTextAlignment.Center;
            RecordNumber.TextColor = ButtonTextColor.SelectedText;
            RecordNumber.Top = 80;
            RecordNumber.Width = 20;

            RecordPosition.Color = ButtonColor.Dark;
            RecordPosition.Height = 10;
            RecordPosition.Left = 100;
            RecordPosition.Text = "";
            RecordPosition.TextAlignment = ButtonTextAlignment.Center;
            RecordPosition.Top = 70;
            RecordPosition.Width = 20;
            RecordPosition.Clickable = true;
            RecordPosition.InitializeDialogWithButtonText = true;
            RecordPosition.DialogCaption = "Position";
            RecordPosition.DialogTextLimit = 2;
            if (boolRecordActivate)
            {
                RecordPosition.Clickable = true;
                RecordPosition.TextColor = ButtonTextColor.SelectedText;
            }
            else
            {
                RecordPosition.Clickable = false;
                RecordPosition.TextColor = ButtonTextColor.LightGrey;
            }

            RecordPositionText.Color = ButtonColor.Dark;
            RecordPositionText.Height = 10;
            RecordPositionText.Left = 80;
            RecordPositionText.Text = "Position #";
            RecordPositionText.TextAlignment = ButtonTextAlignment.Center;
            RecordPositionText.TextColor = ButtonTextColor.SelectedText;
            RecordPositionText.Top = 70;
            RecordPositionText.Width = 20;

            RecordTrackText.Color = ButtonColor.Dark;
            RecordTrackText.Height = 10;
            RecordTrackText.Left = 80;
            RecordTrackText.Text = "Track";
            RecordTrackText.TextAlignment = ButtonTextAlignment.Center;
            RecordTrackText.TextColor = ButtonTextColor.SelectedText;
            RecordTrackText.Top = 60;
            RecordTrackText.Width = 20;

            RecordTrack.Color = ButtonColor.Dark;
            RecordTrack.Height = 10;
            RecordTrack.Left = 100;
            RecordTrack.Text = "";
            RecordTrack.TextAlignment = ButtonTextAlignment.Center;
            RecordTrack.TextColor = ButtonTextColor.SelectedText;
            RecordTrack.Top = 60;
            RecordTrack.Width = 20;

            StartActivate.Color = ButtonColor.Dark;
            StartActivate.Height = 10;
            StartActivate.Left = 70;
            StartActivate.Text = "Activate";
            StartActivate.TextAlignment = ButtonTextAlignment.Center;
            StartActivate.TextColor = ButtonTextColor.Cancel;
            StartActivate.Top = 90;
            StartActivate.Width = 20;
            StartActivate.Clickable = true;

            StartButton.Color = ButtonColor.Dark;
            StartButton.Height = 10;
            StartButton.Left = 90;
            StartButton.Text = "Start";
            StartButton.TextAlignment = ButtonTextAlignment.Center;
            StartButton.Top = 90;
            StartButton.Width = 20;
            if (boolStartActivate)
            {
                StartButton.TextColor = ButtonTextColor.Cancel;
                StartButton.Clickable = true;
            }
            else
            {
                StartButton.TextColor = ButtonTextColor.LightGrey;
                StartButton.Clickable = false;
            }

            StartClose.Color = ButtonColor.Dark;
            StartClose.Height = 10;
            StartClose.Left = 110;
            StartClose.Text = "Close";
            StartClose.TextAlignment = ButtonTextAlignment.Center;
            StartClose.TextColor = ButtonTextColor.SelectedText;
            StartClose.Top = 90;
            StartClose.Width = 20;
            StartClose.Clickable = true;

            StartReady.Color = ButtonColor.Dark;
            StartReady.Height = 10;
            StartReady.Left = 70;
            StartReady.Text = "";
            StartReady.TextAlignment = ButtonTextAlignment.Center;
            StartReady.TextColor = ButtonTextColor.SelectedText;
            StartReady.Top = 80;
            StartReady.Width = 30;

            StartRefresh.Color = ButtonColor.Dark;
            StartRefresh.Height = 10;
            StartRefresh.Left = 100;
            StartRefresh.Text = "Refresh";
            StartRefresh.TextAlignment = ButtonTextAlignment.Center;
            StartRefresh.Top = 80;
            StartRefresh.Width = 30;
            if (boolStartActivate)
            {
                StartRefresh.Clickable = true;
                StartRefresh.TextColor = ButtonTextColor.SelectedText;
            }
            else
            {
                StartRefresh.Clickable = false;
                StartRefresh.TextColor = ButtonTextColor.LightGrey;
            }

            StartSCStandText.Color = ButtonColor.Dark;
            StartSCStandText.Height = 10;
            StartSCStandText.Left = 70;
            StartSCStandText.Text = "Race Start Format:";
            StartSCStandText.TextAlignment = ButtonTextAlignment.Center;
            StartSCStandText.Top = 60;
            StartSCStandText.Width = 30;
            StartSCStandText.TextColor = ButtonTextColor.SelectedText;

            StartSCStand.Color = ButtonColor.Dark;
            StartSCStand.Height = 10;
            StartSCStand.Left = 100;
            StartSCStand.Text = "Standing Start";
            StartSCStand.TextAlignment = ButtonTextAlignment.Center;
            StartSCStand.Top = 60;
            StartSCStand.Width = 30;
            if (boolStartActivate)
            {
                StartSCStand.Clickable = true;
                StartSCStand.TextColor = ButtonTextColor.SelectedText;
            }
            else
            {
                StartSCStand.Clickable = false;
                StartSCStand.TextColor = ButtonTextColor.LightGrey; ;
            }

            RacerStartLocation.AlwaysVisible = true;
            RacerStartLocation.Color = ButtonColor.Dark;
            RacerStartLocation.Height = 10;
            RacerStartLocation.Left = 100;
            RacerStartLocation.Text = "";
            RacerStartLocation.TextAlignment = ButtonTextAlignment.Center;
            RacerStartLocation.TextColor = ButtonTextColor.SelectedText;
            RacerStartLocation.Top = 10;
            RacerStartLocation.Width = 60;

            StartRacerList.Color = ButtonColor.Light;
            StartRacerList.Height = 20;
            StartRacerList.Left = 70;
            StartRacerList.Text = "";
            StartRacerList.TextAlignment = ButtonTextAlignment.Left;
            StartRacerList.TextColor = ButtonTextColor.UnselectedText;
            StartRacerList.Top = 100;
            StartRacerList.Width = 60;

            StartRaceLapsText.Color = ButtonColor.Dark;
            StartRaceLapsText.Height = 10;
            StartRaceLapsText.Left = 70;
            StartRaceLapsText.Text = "Race Distance";
            StartRaceLapsText.TextAlignment = ButtonTextAlignment.Center;
            StartRaceLapsText.TextColor = ButtonTextColor.SelectedText;
            StartRaceLapsText.Top = 70;
            StartRaceLapsText.Width = 30;

            StartRaceLaps.Color = ButtonColor.Dark;
            StartRaceLaps.Height = 10;
            StartRaceLaps.Left = 100;
            StartRaceLaps.Text = "";
            StartRaceLaps.TextAlignment = ButtonTextAlignment.Center;
            StartRaceLaps.Top = 70;
            StartRaceLaps.Width = 30;
            StartRaceLaps.InitializeDialogWithButtonText = true;
            StartRaceLaps.DialogCaption = "Race Distance";
            StartRaceLaps.DialogTextLimit = 4;
            if (boolStartActivate)
            {
                StartRaceLaps.TextColor = ButtonTextColor.SelectedText;
                StartRaceLaps.Clickable = true;
            }
            else
            {
                StartRaceLaps.TextColor = ButtonTextColor.LightGrey;
                StartRaceLaps.Clickable = false;
            }

            handler.Configuration.LFSHost = ip;
            handler.Configuration.LFSHostPort = port;
            handler.Configuration.AdminPass = adminPass;
            handler.Configuration.UseTCP = useTCP;
            handler.Configuration.ProgramName = "LFS Server Control";
            handler.Configuration.UseSplitMessages = true;
            handler.Configuration.Prefix = prefix;
            handler.Configuration.MultiCarTracking = true;
            handler.Configuration.TrackingInterval = 500;
            handler.Configuration.ReconnectRetry = 10;
            handler.Configuration.AutoReconnect = true;
            handler.Configuration.Local = false;

            handler.ButtonClick += new FullMotion.LiveForSpeed.InSim.EventHandlers.ButtonClickHandler(handler_ButtonClick);
            handler.ButtonType += new FullMotion.LiveForSpeed.InSim.EventHandlers.ButtonTypeHandler(handler_ButtonType);
            handler.LFSMessage += new FullMotion.LiveForSpeed.InSim.EventHandlers.MessageEventHandler(handler_LFSMessage);
            handler.LFSState += new FullMotion.LiveForSpeed.InSim.EventHandlers.StateEventHandler(handler_LFSState);
            handler.RaceTrackConnection += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackNewConnectionHandler(handler_RaceTrackConnection);
            handler.RaceTrackConnectionLeave += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackConnectionLeaveHandler(handler_RaceTrackConnectionLeave);
            handler.RaceTrackMultiCarInfo += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackMultiCarInfoHandler(handler_RaceTrackMultiCarInfo);
            handler.RaceTrackPlayer += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerHandler(handler_RaceTrackPlayer);
            handler.RaceTrackPlayerLeave += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerLeaveHandler(handler_RaceTrackPlayerLeave);
            handler.RaceTrackPlayerPits += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerPitsHandler(handler_RaceTrackPlayerPits);
            handler.RaceTrackPlayerRename += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackPlayerRenameHandler(handler_RaceTrackPlayerRename);
            handler.RaceTrackRaceStart += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackRaceStartHandler(handler_RaceTrackRaceStart);
            handler.RaceTrackReorder += new FullMotion.LiveForSpeed.InSim.EventHandlers.RaceTrackReorderHandler(handler_RaceTrackReorder);
        }

        void handler_ButtonClick(InSimHandler sender, ButtonClick e)
        {
            if (e.ButtonId == 11) // Record Position
            {
                if (boolRecordActivate)
                {
                    lfsracer racer = (lfsracer)racerdatabase[e.ConnectionId];
                    TrackRaceLocation trl = new TrackRaceLocation();
                    trl.position = position;
                    trl.X = racer.location.X;
                    trl.Y = racer.location.Y;
                    t.TRL.Add(trl.position, trl);
                }
            }

            if (e.ButtonId == 12) // Export track positions
            {
                if (boolRecordActivate)
                {
                    t.WriteTrackLocations(Track);
                }
            }

            if (e.ButtonId == 13) // close record menu
            {
                handler.DeleteButton(RecordActivate, e.ConnectionId);
                handler.DeleteButton(RecordButton, e.ConnectionId);
                handler.DeleteButton(RecordClose, e.ConnectionId);
                handler.DeleteButton(RecordExport, e.ConnectionId);
                handler.DeleteButton(RecordHeader, e.ConnectionId);
                handler.DeleteButton(RecordNumber, e.ConnectionId);
                handler.DeleteButton(RecordPosition, e.ConnectionId);
                handler.DeleteButton(RecordPositionText, e.ConnectionId);
                handler.DeleteButton(RecordTrack, e.ConnectionId);
                handler.DeleteButton(RecordNumberText, e.ConnectionId);
                handler.DeleteButton(RecordTrackText, e.ConnectionId);
            }

            if (e.ButtonId == 14) // Start race activate system button
            {
                if (boolStartActivate)
                {
                    boolStartActivate = false;
                    StartButton.Clickable = false;
                    StartButton.TextColor = ButtonTextColor.LightGrey;
                    StartRefresh.Clickable = false;
                    StartRefresh.TextColor = ButtonTextColor.LightGrey;
                    StartSCStand.Clickable = false;
                    StartSCStand.TextColor = ButtonTextColor.LightGrey;
                    StartActivate.TextColor = ButtonTextColor.Cancel;
                    StartRaceLaps.TextColor = ButtonTextColor.LightGrey;
                    StartRaceLaps.Clickable = false;
                    handler.ShowButton(StartActivate,e.ConnectionId);
                    handler.ShowButton(StartButton,e.ConnectionId);
                    handler.ShowButton(StartRefresh,e.ConnectionId);
                    handler.ShowButton(StartSCStand,e.ConnectionId);
                    handler.ShowButton(StartRaceLaps, e.ConnectionId);
                }
                else
                {
                    handler.SendMessage("boolStartActivate " + boolStartActivate);
                    boolStartActivate = true;
                    StartButton.Clickable = true;
                    StartButton.TextColor = ButtonTextColor.Cancel;
                    StartRefresh.Clickable = true;
                    StartRefresh.TextColor = ButtonTextColor.SelectedText;
                    StartSCStand.Clickable = true;
                    StartSCStand.TextColor = ButtonTextColor.SelectedText;
                    StartActivate.TextColor = ButtonTextColor.Ok;
                    StartRaceLaps.TextColor = ButtonTextColor.SelectedText;
                    StartRaceLaps.Clickable = true;
                    handler.ShowButton(StartActivate, e.ConnectionId);
                    handler.ShowButton(StartButton, e.ConnectionId);
                    handler.ShowButton(StartRefresh, e.ConnectionId);
                    handler.ShowButton(StartSCStand, e.ConnectionId);
                    handler.ShowButton(StartRaceLaps, e.ConnectionId);
                }
            }

            if (e.ButtonId == 15) // SC/Standing start toggle
            {
                if (StartForm == 1)
                {
                    StartForm = 2;
                    StartSCStand.Text = "SC Start";
                    handler.ShowButton(StartSCStand, e.ConnectionId);
                }
                else
                {
                    StartForm = 1;
                    StartSCStand.Text = "Standing Start";
                    handler.ShowButton(StartSCStand, e.ConnectionId);
                }
            }

            if (e.ButtonId == 17) // Start race
            {
                if ((boolStartActivate))// && (Ready))
                {
                    if (StartSCStand.Text == "Standing Start")
                    {
                        StartLightSequence();
                    }
                    else
                    {
                        if (isHours)
                        {
                            handler.SendMessage("/hours " + racelaps);
                        }
                        else
                        {
                            handler.SendMessage("/laps " + racelaps);
                        }
                    }
                    
                }
                else
                {
                    handler.SendMessageToConnection("Racers are not in position", e.ConnectionId);
                    handler.SendMessageToConnection("Check who in list below", e.ConnectionId);
                }
            }

            if (e.ButtonId == 18) // close start race menu
            {
                handler.DeleteButton(StartActivate, e.ConnectionId);
                handler.DeleteButton(StartButton, e.ConnectionId);
                handler.DeleteButton(StartClose, e.ConnectionId);
                handler.DeleteButton(StartHeader, e.ConnectionId);
                handler.DeleteButton(StartReady, e.ConnectionId);
                handler.DeleteButton(StartRefresh, e.ConnectionId);
                handler.DeleteButton(StartSCStand, e.ConnectionId);
                handler.DeleteButton(StartSCStandText, e.ConnectionId);
                handler.DeleteButton(StartRacerList, e.ConnectionId);
                handler.DeleteButton(StartRaceLaps, e.ConnectionId);
                handler.DeleteButton(StartRaceLapsText, e.ConnectionId);
            }

            if (e.ButtonId == 20) // Refresh ready button
            {
                StartRacerList.Text = null;
                foreach (DictionaryEntry entry in racerdatabase)
                {
                    lfsracer racer = (lfsracer)entry.Value;
                    if (racer.isracing)
                    {
                        if (racer.inPosition == false)
                        {
                            string temp = "";
                            temp += racer.playername;
                            temp += " ";
                            StartRacerList.Text += temp;
                        }
                    }
                }
                handler.ShowButton(StartRacerList, e.ConnectionId);

                if (StartRacerList.Text == null)
                {
                    Ready = true;
                    StartReady.Text = "Ready";
                    StartReady.TextColor = ButtonTextColor.Ok;
                    StartButton.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(StartReady, e.ConnectionId);
                    handler.ShowButton(StartButton, e.ConnectionId);
                }
                else
                {
                    Ready = false;
                    StartReady.Text = "Not Ready";
                    StartReady.TextColor = ButtonTextColor.Cancel;
                    StartButton.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(StartReady, e.ConnectionId);
                    handler.ShowButton(StartButton, e.ConnectionId);
                }
            }

            if (e.ButtonId == 21) // activate record positions menu
            {
                if (boolRecordActivate)
                {
                    boolRecordActivate = false;
                    RecordButton.Clickable = false;
                    RecordButton.TextColor = ButtonTextColor.LightGrey;
                    RecordExport.Clickable = false;
                    RecordExport.TextColor = ButtonTextColor.LightGrey;
                    RecordPosition.Clickable = false;
                    RecordPosition.TextColor = ButtonTextColor.LightGrey;
                    btnFullGridRecord.Clickable = false;
                    RecordActivate.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(RecordActivate, e.ConnectionId);
                    handler.ShowButton(RecordButton, e.ConnectionId);
                    handler.ShowButton(RecordExport, e.ConnectionId);
                    handler.ShowButton(RecordPosition, e.ConnectionId);
                    handler.ShowButton(btnFullGridRecord, e.ConnectionId);
                }
                else
                {
                    boolRecordActivate = true;
                    RecordButton.Clickable = true;
                    RecordButton.TextColor = ButtonTextColor.SelectedText;
                    RecordExport.Clickable = true;
                    RecordExport.TextColor = ButtonTextColor.SelectedText;
                    RecordPosition.Clickable = true;
                    RecordPosition.TextColor = ButtonTextColor.SelectedText;
                    btnFullGridRecord.Clickable = true;
                    RecordActivate.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(RecordActivate, e.ConnectionId);
                    handler.ShowButton(RecordButton, e.ConnectionId);
                    handler.ShowButton(RecordExport, e.ConnectionId);
                    handler.ShowButton(RecordPosition, e.ConnectionId);
                    handler.ShowButton(btnFullGridRecord, e.ConnectionId);
                }
            }

            if (e.ButtonId == 28)
            {
                if (FullGridRecord)
                {
                    FullGridRecord = false;
                    btnFullGridRecord.TextColor = ButtonTextColor.Cancel;
                    handler.ShowButton(btnFullGridRecord, e.ConnectionId);
                    PassConnID = e.ConnectionId;
                }
                else
                {
                    FullGridRecord = true;
                    btnFullGridRecord.TextColor = ButtonTextColor.Ok;
                    handler.ShowButton(btnFullGridRecord, e.ConnectionId);
                    PassConnID = e.ConnectionId;
                }
            }
        }

        void handler_ButtonType(InSimHandler sender, FullMotion.LiveForSpeed.InSim.Events.ButtonType e)
        {
            if (e.ButtonId == 9)
            {
                position = Convert.ToInt16(e.Text);
                RecordPosition.Text = e.Text;
                handler.ShowButton(RecordPosition, e.ConnectionId);
            }

            if (e.ButtonId == 26)
            {
                e.Text.ToLower();
                if (e.Text.EndsWith("h"))
                {
                    isHours = true;
                    racelaps = Convert.ToInt16(e.Text.Replace("h", ""));
                    StartRaceLaps.Text = e.Text;
                    if (racelaps > 24)
                    {
                        racelaps = 0;
                        isHours = false;
                        handler.SendMessageToConnection("Must be 24 hours or lower", e.ConnectionId);
                        StartRaceLaps.Text = "";
                    }
                    handler.ShowButton(StartRaceLaps, e.ConnectionId);
                }
                else
                {
                    isHours = false;
                    racelaps = Convert.ToInt16(e.Text);
                    racelaps++;
                    StartRaceLaps.Text = e.Text;
                    if (racelaps > 1000)
                    {
                        racelaps = 0;
                        isHours = false;
                        handler.SendMessageToConnection("Must be 1000 laps or lower", e.ConnectionId);
                        StartRaceLaps.Text = "";
                    }
                    handler.ShowButton(StartRaceLaps, e.ConnectionId);
                }
            }
        }

        void handler_LFSMessage(InSimHandler sender, Message e)
        {
            if (racerdatabase.ContainsKey(e.ConnectionId))
            {
                lfsracer racer = (lfsracer)racerdatabase[e.ConnectionId];

                if (e.UserType == UserType.Prefix)
                {
                    if ((e.MessageText.Contains("start")) && (racer.isadmin))
                    {
                        handler.ShowButton(StartActivate, e.ConnectionId);
                        handler.ShowButton(StartButton,e.ConnectionId);
                        handler.ShowButton(StartClose,e.ConnectionId);
                        handler.ShowButton(StartHeader,e.ConnectionId);
                        handler.ShowButton(StartReady,e.ConnectionId);
                        handler.ShowButton(StartRefresh,e.ConnectionId);
                        handler.ShowButton(StartSCStand,e.ConnectionId);
                        handler.ShowButton(StartSCStandText, e.ConnectionId);
                        handler.ShowButton(StartRacerList, e.ConnectionId);
                        handler.ShowButton(StartRaceLaps, e.ConnectionId);
                        handler.ShowButton(StartRaceLapsText, e.ConnectionId);
                    }

                    if ((e.MessageText.Contains("record")) && (racer.isadmin))
                    {
                        handler.ShowButton(RecordActivate, e.ConnectionId);
                        handler.ShowButton(RecordButton, e.ConnectionId);
                        handler.ShowButton(RecordClose, e.ConnectionId);
                        handler.ShowButton(RecordExport, e.ConnectionId);
                        handler.ShowButton(RecordHeader, e.ConnectionId);
                        handler.ShowButton(RecordNumber, e.ConnectionId);
                        handler.ShowButton(RecordPosition, e.ConnectionId);
                        handler.ShowButton(RecordPositionText, e.ConnectionId);
                        RecordTrack.Text = Track;
                        handler.ShowButton(RecordTrack, e.ConnectionId);
                        handler.ShowButton(RecordNumberText, e.ConnectionId);
                        handler.ShowButton(RecordTrackText, e.ConnectionId);
                        handler.ShowButton(btnFullGridRecord, e.ConnectionId);
                    }
                }
            }
        }

        void handler_LFSState(InSimHandler sender, State e)
        {
            raceState = e.RaceState.ToString();
            Track = e.ShortTrackName;
        }

        void handler_RaceTrackConnection(InSimHandler sender, RaceTrackConnection e)
        {
            if (e.ConnectionId != 0)
            {
                if (!racerdatabase.ContainsKey(e.ConnectionId))
                {
                    lfsracer racer = new lfsracer(e.UserName, e.ConnectionId);
                    racer.playername = e.PlayerName;
                    racer.isadmin = e.IsAdmin;
                    racer.isremote = e.IsRemote;
                    racerdatabase.Add(e.ConnectionId, racer);
                }
            }
        }

        void handler_RaceTrackConnectionLeave(InSimHandler sender, RaceTrackConnectionLeave e)
        {
            if (racerdatabase.ContainsKey(e.ConnectionId))
            {
                racerdatabase.Remove(e.ConnectionId);
            }
        }

        void handler_RaceTrackMultiCarInfo(InSimHandler sender, RaceTrackMultiCarInfo e)
        {
            Console.WriteLine("boolStartActivate " + boolStartActivate + "    boolRecordActivate " + boolRecordActivate);
            if ((boolStartActivate) || (boolRecordActivate))
            {
                for (int i = 0; i < Math.Min(8, e.CarInfo.Length); i++)
                {
                    lfsracer racer = (lfsracer)racerdatabase[(getConnectionid(e.CarInfo[i].PlayerId))];
                    if (racer != null)
                    {
                        racer.Speed = e.CarInfo[i].Speed;
                        //handler.SendMessage(racer.username + " " + e.CarInfo[i].Speed);
                        //Vector temp = new Vector(e.CarInfo[i].Location.X, e.CarInfo[i].Location.Y, 0);
                        //racer.location = temp;
                        racer.location = e.CarInfo[i].Location;
                        racer.postion = e.CarInfo[i].RacePosition;
                        Console.WriteLine("mci update");
                    }
                }
            }

            if ((boolRecordActivate) && (FullGridRecord))
            {
                for (int i = 0; i < Math.Min(8, e.CarInfo.Length); i++)
                {
                    lfsracer racer = (lfsracer)racerdatabase[(getConnectionid(e.CarInfo[i].PlayerId))];
                    TrackRaceLocation trl = new TrackRaceLocation();
                    if (racer != null)
                    {
                        racer.Speed = e.CarInfo[i].Speed;
                        //handler.SendMessage(racer.username + " " + e.CarInfo[i].Speed);
                        Vector temp = new Vector(e.CarInfo[i].Location.X, e.CarInfo[i].Location.Y, 0);
                        racer.location = temp;
                        racer.postion = e.CarInfo[i].RacePosition;

                        trl.position = racer.postion;
                        trl.X = racer.location.X;
                        trl.Y = racer.location.Y;
                        t.TRL.Add(trl.position, trl);
                    }
                }
                FullGridRecord = false;
                btnFullGridRecord.TextColor = ButtonTextColor.Cancel;
                RecordNumber.Text = Convert.ToString(t.TRL.Count);
                handler.ShowButton(btnFullGridRecord, PassConnID);
                handler.ShowButton(RecordNumber, PassConnID);
            }
        }

        void handler_RaceTrackPlayer(InSimHandler sender, RaceTrackPlayer e)
        {
            if (racerdatabase.ContainsKey(e.ConnectionId))
            {
                lfsracer racer = (lfsracer)racerdatabase[e.ConnectionId];
                racer.plate = e.Plate;
                racer.playerid = e.PlayerId;
                racer.isracing = true;
            }
        }

        void handler_RaceTrackPlayerLeave(InSimHandler sender, RaceTrackPlayerLeave e)
        {
            if (racerdatabase.ContainsKey(getConnectionid(e.PlayerId)))
            {
                lfsracer racer = (lfsracer)racerdatabase[(getConnectionid(e.PlayerId))];
                racer.isracing = false;
            }
        }

        void handler_RaceTrackPlayerPits(InSimHandler sender, RaceTrackPlayerPits e)
        {
            if (racerdatabase.ContainsKey(getConnectionid(e.PlayerId)))
            {
                lfsracer racer = (lfsracer)racerdatabase[(getConnectionid(e.PlayerId))];
                racer.isracing = false;
            }
        }

        void handler_RaceTrackPlayerRename(InSimHandler sender, RaceTrackPlayerRename e)
        {
            if (racerdatabase.ContainsKey(e.ConnectionId))
            {
                lfsracer racer = (lfsracer)racerdatabase[e.ConnectionId];
                racer.playername = e.PlayerName;
                racer.plate = e.Plate;
            }
        }

        void handler_RaceTrackRaceStart(InSimHandler sender, RaceTrackRaceStart e)
        {
            if (boolStartActivate)
            {
                t.ReadTrackLocations(e.ShortTrackName);
                //Thread StoreRaceStartPositionThread = new Thread(new ThreadStart(StoreRaceStartPosition));
                //StoreRaceStartPositionThread.Start();
                StoreRaceStartPosition();
                Thread CheckRacePositionThread = new Thread(new ThreadStart(CheckRacePosition));
                CheckRacePositionThread.Start();
                //CheckRacePosition();
            }
        }

        void handler_RaceTrackReorder(InSimHandler sender, RaceTrackReorder e)
        {
            if (boolStartActivate)
            {
                reodatabase.Clear();
                for (int i = 0; i < e.OrderedPlayerIds.Length; i++)
                {
                    reodatabase.Add(e.OrderedPlayerIds[i], i);
                }
            }
        }

        public void StoreRaceStartPosition()
        {
            try
            {
                for (int i = 0; i < reodatabase.Count; i++)
                {
                    //lfsracer racer = (lfsracer)racerdatabase[GetReoPlayerID(i)];
                    lfsracer racer = (lfsracer)racerdatabase[getConnectionid(GetReoPlayerID(i))];
                    TrackRaceLocation trl = (TrackRaceLocation)t.TRL[i + 1];

                    racer.racestartlocation = null;
                    racer.postion = i + 1;
                    Vector temp = new Vector(trl.X, trl.Y, 0);
                    Console.WriteLine(racer.username + " " + temp.X);
                    racer.racestartlocation = temp;
                }
            }
            catch (Exception)
            {
                handler.SendMessage("catch");
            }
        }

        public void CheckRacePosition()
        {
            while (boolStartActivate)
            {
                for (int i = 0; i < reodatabase.Count; i++)
                {
                    lfsracer racer = (lfsracer)racerdatabase[getConnectionid(GetReoPlayerID(i))];

                    if (racer.racestartlocation != null)
                    {
                        int DiffX = (racer.location.X - racer.racestartlocation.X) / (centimeter * sensitivity);
                        int DiffY = (racer.location.Y - racer.racestartlocation.Y) / (centimeter * sensitivity);

                        //Console.WriteLine(racer.username + " " + racer.racestartlocation.X + " " + racer.location.X);

                        string direction = "";
                        string distance = "";

                        if (DiffX == 0)
                            direction = " || ";
                        else
                            if (DiffX < 0)
                                direction = " >> ";
                            else
                                direction = " << ";

                        if (DiffY == 0)
                            distance = " -- ";
                        else
                            if (DiffY < 0)
                                distance = Math.Abs(DiffY) + " CM to go";
                                //distance = DiffY + " CM to go";
                            else
                                distance = "Backup, too far";

                        if (DiffX == 0 && DiffY == 0)
                        {
                            RacerStartLocation.Text = "In position, don't move";
                            racer.inPosition = true;
                        }
                        else
                        {
                            RacerStartLocation.Text = "Move to " + direction + " and " + distance;
                            racer.inPosition = false;
                        }
                        Console.WriteLine(RacerStartLocation.Text);
                        handler.ShowButton(RacerStartLocation, racer.connectionid);
                        Thread.Sleep(1000);
                    }
                }
            }
        }

        public void StartLightSequence()
        {
            if (boolStartActivate)
            {
                boolStartActivate = false;
                handler.DeleteButton(RacerStartLocation, true);

                Random random = new Random();
                int delay = random.Next(2000, 5000);
                
                handler.ShowButton(lights[0], false);
                Thread.Sleep(1000);
                handler.ShowButton(lights[1], false);
                Thread.Sleep(1000);
                handler.ShowButton(lights[2], false);
                Thread.Sleep(1000);
                handler.ShowButton(lights[3], false);
                Thread.Sleep(1000);
                handler.ShowButton(lights[4], false);

                Thread.Sleep(delay);
                foreach (DictionaryEntry entry in racerdatabase)
                {
                    lfsracer racer = (lfsracer)entry.Value;
                    if (racer.Speed != 0)
                    {
                        handler.SendMessage("penalty");
                    }
                }
                
                handler.DeleteButton(lights[0], false);
                handler.DeleteButton(lights[1], false);
                handler.DeleteButton(lights[2], false);
                handler.DeleteButton(lights[3], false);
                handler.DeleteButton(lights[4], false);

                if (isHours)
                {
                    handler.SendMessage("/hours " + racelaps);
                }
                else
                {
                    handler.SendMessage("/laps " + racelaps);
                }
            }
        }

        public byte GetReoPlayerID(int i) // get playerid from reodb from position i
        {
            try
            {
                foreach (DictionaryEntry Entry in reodatabase)
                {
                    int test = (int)Entry.Value;
                    if (test == i)
                        return (byte)Entry.Key;
                }
                return (byte)0;
            }
            catch (Exception ex)
            {
                return (byte)0;
            }
        }

        public void Start()
        {
            try
            {
                Assembly SampleAssembly = Assembly.Load(Assembly.GetExecutingAssembly().FullName);
                foreach (Attribute a in SampleAssembly.GetCustomAttributes(true))
                {
                    if (a is AssemblyTitleAttribute)
                    {
                        ProgramTitle = (a as AssemblyTitleAttribute).Title;
                    }
                    if (a is AssemblyFileVersionAttribute)
                    {
                        ProgramVersion = (a as AssemblyFileVersionAttribute).Version;
                    }
                    if (a is AssemblyCompanyAttribute)
                    {
                        ProgramCompany = (a as AssemblyCompanyAttribute).Company;
                    }
                }

                Console.Title = ProgramTitle + " " + ProgramVersion;
                Console.WriteLine(ProgramTitle);
                Console.WriteLine("Version: " + ProgramVersion);
                Console.WriteLine(ProgramCompany);
                Console.WriteLine("Connecting");
                handler.Initialize(10);
                Console.WriteLine("Connected");
                handler.SendMessage("Race Control System Restarting...");
                handler.SendMessage(ProgramTitle);
                handler.SendMessage("Version: " + ProgramVersion);
                handler.SendMessage(ProgramCompany);
                handler.RequestConnectionInfo();
                handler.RequestPlayerInfo();
            }
            catch (Exception ex)
            {
                Console.WriteLine();
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                Console.WriteLine(" ");
                Console.WriteLine(ProgramTitle + " could not connect. Please check your ip, port and admin pass settings.");
                Console.ReadLine();
                Environment.Exit(0);
            }
        }

        public void Threading()
        {
            while (handler.State == InSimHandler.HandlerState.Connected)
            {
                Thread.Sleep(1);
            }
        }

        public byte getConnectionid(byte playerid)
        {
            try
            {
                foreach (System.Collections.DictionaryEntry Entry in this.racerdatabase)
                {
                    lfsracer racer = (lfsracer)Entry.Value;
                    if (racer.playerid == playerid)
                        return racer.connectionid;
                }
                return (byte)0;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return (byte)0;
            }
        }
    }
}
